<template>
  <div
    v-if="!isCompatibleversion"
    class="page-header"
    :class="{ 'page-header-filter': isFilter }"
    :style="{
      'min-height': '44px',
      background: pageHeaderBackground,
      position: isFixed ? 'fixed' : null,
      'border-bottom':
        isShadow && !isTransparent ? '1px solid rgba(0, 0, 0, 10%)' : 'initial',
    }"
  >
    <!-- 状态栏 -->
    <div
      :style="{ height: `${statusBarHeight}` }"
      :class="{ statusBar: statusBarHeight == '0px' }"
    ></div>
    <!-- 导航 -->
    <div v-if="isShowNav" class="nav" style="height: 44px">
      <!-- 左侧 -->
      <!-- <ClientOnly> -->
      <div
        ref="navLeftRef"
        class="nav-left"
        :style="{ 'min-width': equalWidth }"
      >
        <template v-if="isShowLeft">
          <template v-if="leftArrow">
            <img
              class="nav-left-btn"
              :src="leftBtnIcon"
              @click="handleBack(false)"
            />
          </template>
          <!-- icon插槽 -->
          <slot v-else name="left"></slot>
          <!-- 1.1.0 增加❌点击直接返回 app -->
          <img
            v-if="isShowLeftAppBack"
            class="nav-left-btn"
            style="margin-left: 20px"
            :src="leftCloseBtnIcon"
            @click="handleBack(true)"
          />
        </template>
      </div>
      <!-- </ClientOnly> -->

      <!-- 标题 -->
      <div
        class="nav-title"
        style="line-height: 44px"
        :style="{
          color: titleColor
            ? titleColor
            : isThreshold && gradientTitleColor
            ? gradientTitleColor
            : !isFilter && whiteTheme
            ? `#fff`
            : `#141924`,
        }"
      >
        {{ title }}
      </div>
      <!-- 右侧 icon 插槽 -->
      <div
        ref="navRightRef"
        class="nav-right"
        :style="{ 'min-width': equalWidth }"
      >
        <template v-if="isCusRightBtns">
          <slot name="right"></slot>
        </template>
        <template v-else>
          <slot name="right"></slot>
          <img
            v-if="whiteTheme"
            class="nav-right-backapp"
            src="/image/backapp-fff.svg"
            @click="handleBackRight(true)"
          />
          <img
            v-else
            class="nav-right-backapp"
            src="/image/backapp.svg"
            @click="handleBackRight(true)"
          />
        </template>
      </div>
    </div>
  </div>
  <div v-else>
    <slot name="right"></slot>
  </div>
  <!-- 导航后面的占位元素 -->
  <div
    v-if="placeholder && !isCompatibleversion && isShowNav"
    :class="{ 'occupy-statusBar': statusBarHeight == '0px' }"
    :style="{
      height:
        statusBarHeight == '0px' ? '44px' : `calc(${statusBarHeight} + 44px)`,
    }"
  ></div>
</template>

<script>
import { ref, defineComponent, computed } from "vue";
import { useGlobalStore } from "~~/store/global";
import { navigateBack, isAndroid, isiOS, getOssFileUrl } from "@/utils";
import { compare } from "~/utils/calculation";
import { useWindowSize } from "@vant/use";
import {
  useScroll,
  useScreenSafeArea,
  useDevicePixelRatio,
} from "@vueuse/core";
import { JUMPAPPS } from "~/config";
import { useEventBus } from "@vueuse/core";

/**
 * @description: 自定义导航
 * 1. 状态高度从 app 获取，获取不到使用变量来撑开
 * 2. 导航支持： 高斯模糊、渐变色、白色主题、自定义颜色
 * 3. 导航左右都有插槽可以使用
 * 4. 组件加载完成返回当前导航高度
 *  高斯模糊使用：
 * <NavBar
      title="标题"
      isTransparent
      navScorllFilter
      :scrollEl="scrollEl"
    />
    script: const scrollEl = ref(); // 接收滚动事件，传递给导航组件
 *  渐变色例子：
    <NavBar
      title="标题"
      isTransparent
      navScorllColor="#0051E7"
      :scrollEl="scrollEl"
    />
 */
export default defineComponent({
  name: "navBar",
  props: {
    // 白色主题，默认的返回按钮和标题都是白色的
    whiteTheme: {
      type: Boolean,
      default: false,
    },
    // 是否显示导航底部阴影
    isShadow: {
      type: Boolean,
      default: true,
    },
    // 是否显示,nav 容器
    isShowNav: {
      type: Boolean,
      default: true,
    },
    // 导航栏是否fixed固定在顶部
    isFixed: {
      type: Boolean,
      default: false,
    },
    // 导航占位 box
    placeholder: {
      type: Boolean,
      default: true,
    },
    // 是否显示左侧功能区域
    isShowLeft: {
      type: Boolean,
      default: true,
    },
    // 是否显示左侧返回按钮
    leftArrow: {
      type: Boolean,
      default: true,
    },
    // 是否显示左侧返回APP按钮
    isShowLeftAppBack: {
      type: Boolean,
      default: false,
    },
    // 自定义左侧按钮图片，优先级高于gradientLeftIcon（建议 leftIcon 请使用 public 目录下的图片）
    leftIcon: {
      type: String,
      default: "",
    },
    title: {
      type: String,
      default: "",
    },
    titleColor: {
      type: String,
      default: "",
    },
    // 是否自定义右侧按钮
    isCusRightBtns: {
      type: Boolean,
      default: false,
    },
    // 渐变色场景-自定义返回按钮
    gradientLeftIcon: {
      type: String,
      default: "",
    },
    // 渐变色场景-自定义返回按钮
    gradientLeftCloseIcon: {
      type: String,
      default: "",
    },
    // 渐变色场景-标题颜色
    gradientTitleColor: {
      type: String,
      default: "",
    },
    // 导航变白-偏移量: 注意父级元素一定要设置 overflow-y: scroll;
    navScorllOffset: {
      type: Number,
      default: 25,
    },
    // 导航渐变色（配合navScorllOffset使用）：
    navScorllColor: {
      type: String,
      default: "",
    },
    // 高斯模糊效果（配合navScorllOffset使用）：
    navScorllFilter: {
      type: Boolean,
      default: false,
    },
    // 导航背景是否透明
    isTransparent: {
      type: Boolean,
      default: false,
    },
    // 导航背景颜色
    bgColor: {
      type: String,
      default: "",
    },
    // 滚动元素的Ref（一般是页面跟元素）
    scrollEl: {
      type: Object,
      default: () => null,
    },
    // 自定义返回函数
    customBackFn: Function,
    // 自定义 右侧关闭函数
    customCloseFn: Function,
  },
  emits: ["getNavBarHeight", "thresholdChange"],
  setup(props, { attrs, emit }) {
    // console.log("导航参数:", props);
    const globalStore = useGlobalStore();
    const { width } = process.client ? useWindowSize() : { width: ref(320) };
    const { pixelRatio } = useDevicePixelRatio();
    // const { top, right, bottom, left } = useScreenSafeArea();
    // console.log("--top--", top.value, "--bottom--", bottom, "--left--", left);

    const imgUrl = getOssFileUrl({
      arrowFFF: "/image/left-arrow-fff.png",
      arrow: "/image/left-arrow.png",
      close: "/image/nav-bar-close.svg",
      closeFFF: "/image/nav-bar-closefff.svg",
    });

    // 左侧按钮
    const leftBtnIcon = computed(() => {
      if (props.leftIcon) {
        return props.leftIcon;
      }
      //  渐变色按钮配置
      else if (isThreshold.value && props.gradientLeftIcon) {
        return props.gradientLeftIcon;
      } else if (props.whiteTheme && !isFilter.value) {
        return imgUrl.arrowFFF;
      } else {
        return imgUrl.arrow;
      }
    });

    // 左侧返回 app 按钮
    const leftCloseBtnIcon = computed(() => {
      //  渐变色按钮配置
      if (isThreshold.value && props.gradientLeftCloseIcon) {
        return props.gradientLeftCloseIcon;
      } else if (props.whiteTheme && !isFilter.value) {
        return imgUrl.closeFFF;
      } else {
        return imgUrl.close;
      }
    });
    const equalWidth = ref("auto");
    const navLeftRef = ref();
    const navRightRef = ref();
    const updateWidths = () => {
      nextTick(() => {
        const leftWidth = navLeftRef.value ? navLeftRef.value.offsetWidth : 0;
        const rightWidth = navRightRef.value
          ? navRightRef.value.offsetWidth
          : 0;
        const maxWidth = Math.max(leftWidth, rightWidth) + "px";
        equalWidth.value = maxWidth;
      });
    };

    // 状态栏高度: 默认 0
    const statusBarHeight = computed(() => {
      // if (!process.client) return "0px";
      if (isiOS.value) {
        console.log(`iOS状态栏:${globalStore.statusBarHeight}`);
        return `${globalStore.statusBarHeight || 0}px`;
      } else {
        const zb =
          globalStore.statusBarHeight / (width.value * pixelRatio.value);
        // const vw = `${zb * 100 || 0}vw`;
        const px = `${zb * width.value || 0}px`;
        console.log(`安卓状态栏:${px}`);
        return px;
      }
    });
    // 导航高度 单位px,用于返回不带单位的数值
    const navBarHeight = computed(() => {
      if (isiOS.value) {
        return (globalStore.statusBarHeight || 0) + 44;
      } else {
        const zb =
          globalStore.statusBarHeight / (width.value * pixelRatio.value);
        // const vw = `${zb * 100 || 0}vw`;
        const px = (zb * width.value || 0) + 44;
        return px;
      }
    });

    /**
     * @description: 老版本导航兼容处理
     * 安卓 1.8.83 以前版本，导航无法隐藏，需要隐藏自己的导航; 桥接新版本会根据-是否包含https://pre-bdc.btcdana.org/fx/来决定时候隐藏导航；调用bridge.hideToolbar(只会隐藏标题，后面的版本会隐藏导航)返回导航高度
     * iOS 1.2.14 以前版本，使用原生导航，只能改标题；新版本连接中加参数，来隐藏导航；isCompatibleversion用来控制将右侧的按钮插槽 添加到页面右上角；
     */
    const isCompatibleversion = ref(false); // 是否使用兼容版本处理
    const compatibleAndroidList = JUMPAPPS().navBar(); // 需要兼容的,安卓版本号
    const compatible = () => {
      // 安卓
      if (isAndroid.value) {
        let packageId = bridge.getAppPackageId();
        const basePackageId = compatibleAndroidList.find((e) => {
          return e.split("-")[0] === globalStore.packagePrefix;
        });

        if (basePackageId) {
          let compareVersion = compare(packageId, basePackageId);
          if (compareVersion == -1) {
            isCompatibleversion.value = true;
          } else {
            globalStore.statusBarHeight = bridge.hideToolbar() || 0; // 调用原生app的函数(返回状态栏高度)
            // console.log(`安卓状态栏:${globalStore.statusBarHeight}`);
          }
        }
      }
      // iOS(目前没有绿包和BtcDanaElite)
      if (isiOS.value) {
        // console.log(`iOS 状态栏:${globalStore.statusBarHeight}`);
        if (
          globalStore.packagePrefix === "BtcDana" ||
          globalStore.packagePrefix === "BtcDana.IOS"
        ) {
          // 获取 packageId
          let packageId = bridge.getAppPackageId();
          let basePackageId = "BtcDana.IOS-1.2.15-com.indone.online-ios";
          let compareVersion = compare(packageId, basePackageId);

          if (compareVersion == -1) {
            isCompatibleversion.value = true;
            bridge.setTitle(props.title);
          } else {
            isCompatibleversion.value = false;
          }
        }
      }
    };

    /**
     * 监听页面滚动,来决定是否显示渐变、高斯模糊效果
     * */
    const scrollHock = ref();
    let scrollHockInit = false;
    watch(
      () => props.scrollEl,
      (newVal) => {
        if (newVal && !scrollHock.value && !scrollHockInit) {
          scrollHockInit = true;
          try {
            scrollHock.value = useScroll(newVal, { behavior: "smooth" });
          } catch (error) {
            console.log("--useScroll--失败", error);
          }
        }
      },
      {
        immediate: true,
      }
    );

    let proportion = ref(-1);
    let isThresholdTrue = false;
    // 捕获滚动偏移量。是否达到阈值
    const isThreshold = computed(() => {
      if (!scrollHock.value) {
        isThresholdTrue = false;
        return false;
      }
      if (!props.navScorllFilter) {
        proportion.value = (scrollHock.value.y / props.navScorllOffset).toFixed(
          1
        );
      }
      if (scrollHock.value.y > props.navScorllOffset) {
        // console.log(isThreshold.value, "--偏移量--", scrollHock.value.y);
        isThresholdTrue = true;
        return true;
      } else if (
        isThresholdTrue &&
        scrollHock.value.y < props.navScorllOffset
      ) {
        isThresholdTrue = false;
        return false;
      } else {
        isThresholdTrue = false;
        return false;
      }
    });

    watch(
      () => isThreshold.value,
      (newVal) => {
        if (typeof newVal == "boolean") emit("thresholdChange", newVal);
      }
    );
    /**
     * @description: 导航背景色；优先级如下
     * 1. 高斯模糊效果
     * 2. 滚动的场景，从浅到深渐变
     * 3. 透明背景颜色
     * 4. 指定背景色
     * 5. 默认白色
     */
    const pageHeaderBackground = computed(() => {
      if (!props.isShowNav) return "transparent";
      if (isThreshold.value) {
        if (!props.navScorllFilter) {
          return props.navScorllColor;
        } else {
          return `linear-gradient(180deg, rgba(255, 255, 255, 50%) 0%, rgba(255, 255, 255, 0%) 100%)`;
        }
      } else if (
        !props.navScorllFilter &&
        !props.bgColor &&
        props.isTransparent &&
        proportion.value <= 1 &&
        proportion.value > 0
      ) {
        let c = colorRgba(props.navScorllColor);
        c = c.replace(",1)", `,${proportion.value})`);
        return c;
      } else {
        return props.isTransparent
          ? "transparent"
          : props.bgColor
          ? props.bgColor
          : props.navScorllColor
          ? props.navScorllColor
          : "#fff";
      }
    });

    // 是不是高斯模糊效果场景
    const isFilter = computed(() => {
      return isThreshold.value && props.navScorllFilter;
    });

    onMounted(() => {
      if (process.client) {
        // 1. 兼容 2023.10.19 之前的app版本
        compatible();
        // 2. 传递滚动事件函数
        // console.log("navBar--导航高度--", statusBarHeight.value);
        // 3. 导航高度（包含状态栏）
        emit("getNavBarHeight", navBarHeight.value);
        // 4. 动态计算导航标题宽度
        updateWidths();
      }
    });

    // 16进制转换为RGBA
    const colorRgba = function (val) {
      // 16进制颜色值的正则
      var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
      // 把颜色值变成小写
      var color = val.toLowerCase();
      if (reg.test(color)) {
        // 如果只有三位的值，需变成六位，如：#fff => #ffffff
        if (color.length === 4) {
          var colorNew = "#";
          for (var i = 1; i < 4; i += 1) {
            colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
          }
          color = colorNew;
        }
        // 处理六位的颜色值，转为RGB
        var colorChange = [];
        for (var i = 1; i < 7; i += 2) {
          colorChange.push(parseInt("0x" + color.slice(i, i + 2)));
        }
        return "rgba(" + colorChange.join(",") + ",1)";
      } else {
        return color;
      }
    };
    // 拦截 APP 侧滑和虚拟返回按键，事件
    const onInterceptAppBack = useEventBus("bridge-onInterceptAppBack-emit");
    onInterceptAppBack.on((e) => {
      handleBack();
    });

    // 左侧-按钮事件
    const handleBack = async (isBackApp = false) => {
      if (props.customBackFn) {
        return props.customBackFn();
      } else {
        navigateBack(-1, isBackApp);
      }
    };
    // 右侧-侧按钮事件
    const handleBackRight = async (isBackApp = false) => {
      if (props.customCloseFn) {
        return props.customCloseFn();
      } else {
        navigateBack(-1, isBackApp);
      }
    };

    return {
      statusBarHeight,
      isCompatibleversion,
      pageHeaderBackground,
      isThreshold,
      isFilter,
      leftBtnIcon,
      scrollHock,
      leftCloseBtnIcon,
      navLeftRef,
      navRightRef,
      equalWidth,
      handleBack,
      handleBackRight,
    };
  },
});
</script>

<style lang="scss" scoped>
@mixin multi-line-omit($number) {
  display: -webkit-box;
  display: -moz-box;
  -webkit-line-clamp: $number;
  -moz-line-clamp: $number;
  word-break: break-all; // 纯字母、数字
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
}

.page-header {
  width: 100vw;
  overflow: hidden;
  z-index: 999;
  will-change: opacity;

  &-filter {
    backdrop-filter: blur(8 * 2px);
  }

  .nav {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;

    padding: 0 20px;

    &-left {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: flex-start;

      &-btn {
        width: 22 * 2px;
        height: 44px;
      }
    }

    &-title {
      @include multi-line-omit(1);
      height: 100%;
      text-align: center;
      color: #141924;
      font-weight: 590;
      font-size: 34px;
    }

    &-right {
      min-width: 89px;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      &-backapp {
        width: 22 * 2px;
        height: 22 * 2px;
      }
    }
  }
}

.statusBar {
  padding-top: constant(safe-area-inset-top); // 实测 inpone xs 可行
  padding-top: env(safe-area-inset-top);
}

.occupy-statusBar {
  margin-bottom: constant(
    safe-area-inset-top
  ); // 实测 inpone xs 可行；这么写是因为 padding-top大于height的特殊情况
  margin-bottom: env(safe-area-inset-top);
}
</style>
